package com.yuyou.fn.balance.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.github.wens.framework.service.impl.SuperServiceImpl;
import com.github.wens.mybatisplus.examples.Example;
import com.github.wens.mybatisplus.plugins.Page;
import com.yuyou.fn.balance.entity.BalanceTransfer;
import com.yuyou.fn.balance.mapper.BalanceTransferMapper;
import com.yuyou.fn.balance.service.IBalanceTransferService;
import com.yuyou.fn.balance.vo.BalanceTransferQueryVo;
import com.yuyou.fn.common.exception.BusException;
import com.yuyou.fn.common.util.*;
import com.yuyou.fn.educational.entity.Campus;
import com.yuyou.fn.educational.entity.Student;
import com.yuyou.fn.educational.service.ICampusService;
import com.yuyou.fn.educational.service.IStudentService;
import com.yuyou.fn.settlement.entity.MainAccount;
import com.yuyou.fn.settlement.service.IMainAccountService;
import com.yuyou.fn.settlement.service.ISettlementService;
import org.apache.commons.lang3.time.DateUtils;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 *
 * BalanceTransfer 表数据服务层接口实现类
 *
 */
@Service
public class BalanceTransferServiceImpl extends SuperServiceImpl<BalanceTransferMapper, BalanceTransfer,Long> implements IBalanceTransferService {

    @Resource
    private ISettlementService settlementService;

    @Resource
    private ICampusService campusService;

    @Resource
    private IMainAccountService mainAccountService;

    @Resource
    private IStudentService studentService;

    @Resource
    private Redisson redisson ;

    @Override
    public Page<BalanceTransfer> findBalanceTransferByQuery(BalanceTransferQueryVo balanceTransferQueryVo, List<Long> campusIds, Integer pageNo, Integer pageSize) {

        if(balanceTransferQueryVo.getEndTime() != null ){
            balanceTransferQueryVo.setEndTime(DateUtils.addDays(balanceTransferQueryVo.getEndTime(), 1 ));
        }

        Example<BalanceTransfer> example = BalanceTransfer.createExample();

        Example.Criteria criteria = example.createCriteria();
        CriteriaUtils.fillCondition(criteria,balanceTransferQueryVo);

        criteria.andIn("acceptCampusId" , campusIds );

        if(campusIds == null || campusIds.size() == 0 ){
            criteria.andEqualTo("acceptCampusId" , 0l ); // not exist
        }

        example.orderBy("createTime").desc();

        return findPageByExample(example,pageNo , pageSize );
    }

    @Override
    public Long countBalanceTransferByQuery(BalanceTransferQueryVo balanceTransferQueryVo, List<Long> campusIds) {
        if(balanceTransferQueryVo.getEndTime() != null ){
            balanceTransferQueryVo.setEndTime(DateUtils.addDays(balanceTransferQueryVo.getEndTime(), 1 ));
        }

        Example<BalanceTransfer> example = BalanceTransfer.createExample();

        Example.Criteria criteria = example.createCriteria();
        CriteriaUtils.fillCondition(criteria,balanceTransferQueryVo);

        criteria.andIn("acceptCampusId" , campusIds );

        if(campusIds == null || campusIds.size() == 0 ){
            criteria.andEqualTo("acceptCampusId" , 0l ); // not exist
        }

      //  example.orderBy("createTime").desc();

        return countByExample(example);
    }

    @Transactional
    @Override
    public void audit(Long balanceTransferId, Integer status, String auditRemark, Principals.Principal principal) {

        if(!Arrays.asList(1,2).contains(status)){
            throw new IllegalArgumentException("Invalid status");
        }

        if(principal.id.equals(findById(balanceTransferId,"operatorId").getOperatorId())){
            throw new BusException("很抱歉，您无法审批自己发起的申请！");
        }

        BalanceTransfer balanceTransfer  = new BalanceTransfer() ;
        balanceTransfer.setStatus(status);
        balanceTransfer.setAuditId(principal.id);
        balanceTransfer.setAuditName(principal.name);
        balanceTransfer.setAuditRemark(auditRemark);
        balanceTransfer.setAuditTime(TimeUtils.now());

        Example<BalanceTransfer> example = BalanceTransfer.createExample();
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("balanceTransferId" ,balanceTransferId);
        criteria.andEqualTo("status" , 0 );

        if(updateSelectiveByExample(balanceTransfer ,example )){
            BalanceTransfer balanceTransfer1 = findById(balanceTransferId);
            if(status == 1 ){
                settlementService.increaseBalance(balanceTransfer1.getDestMainAccountId() , balanceTransfer1.getAmount(), balanceTransfer1.getApplierMainAccountName() + "转让余额");
            }else if(status == 2 ){
                settlementService.increaseBalance(balanceTransfer1.getApplierMainAccountId() , balanceTransfer1.getAmount(), "转让审核失败，余额退回");
            }
        }
    }

    @Transactional
    @Override
    public void save(Principals.Principal principal , Long applierMainAccountId, Long destMainAccountId, Long acceptCampusId, BigDecimal amount, String reasonRemark) {
        RLock lock = redisson.getLock(String.format("mainAccountId:%s",applierMainAccountId ));
        if (lock.tryLock()) {
            try {

                if (amount.doubleValue()<=0d){
                    throw new BusException("输入的金额必须大于0");
                }
                BalanceTransfer balanceTransfer = new BalanceTransfer();
                balanceTransfer.setApplierMainAccountId(applierMainAccountId);
                balanceTransfer.setDestMainAccountId(destMainAccountId);
                balanceTransfer.setAcceptCampusId(acceptCampusId);
                balanceTransfer.setAmount(amount);
                balanceTransfer.setOperatorId(principal.id);
                balanceTransfer.setOperatorName(principal.name);
                balanceTransfer.setReasonRemark(reasonRemark);
                balanceTransfer.setStatus(0);

                Campus campus = campusService.findById(acceptCampusId, "campusName" ,"areaTeamId");
                if(campus != null ){
                    balanceTransfer.setAcceptCampusName(campus.getCampusName());
                    balanceTransfer.setAreaTeamId(campus.getAreaTeamId());
                }
                MainAccount mainAccount = mainAccountService.findById(applierMainAccountId, "name" , "tag" , "balanceAmount");
                MainAccount destMainAccount = mainAccountService.findById(destMainAccountId, "name" , "tag" , "balanceAmount");

                if(mainAccount == null ){
                    throw new IllegalArgumentException("Invalid applierMainAccountId");
                }

                if(destMainAccount == null ){
                    throw new IllegalArgumentException("Invalid destMainAccountId");
                }

                if(BigDecimals.compare( amount , mainAccount.getBalanceAmount() ) > 0  ){
                    throw new BusException("转让金额大于账户余额");
                }

                balanceTransfer.setApplierMainAccountName(mainAccount.getName());
                balanceTransfer.setDestMainAccountName(destMainAccount.getName());
                balanceTransfer.setRemainAmount(mainAccount.getBalanceAmount().subtract(amount));
                JSONObject jsonObject = new JSONObject();
                if("student".equals(mainAccount.getTag())){
                    jsonObject = buildExtraStudent(applierMainAccountId , destMainAccountId );
                }

                balanceTransfer.setExtra(jsonObject.toJSONString());
                balanceTransfer.setCreateTime(TimeUtils.now());
                balanceTransfer.setUpdateTime(TimeUtils.now());
                insertSelective(balanceTransfer);
                settlementService.decreaseBalance(applierMainAccountId,amount,"转让");
            } finally {
                lock.unlock();
            }
        }



    }

    private JSONObject buildExtraStudent(Long studentId , Long destStudentId ) {
        JSONObject jsonObject = new JSONObject();
        List<Student> students = studentService.findByIds(Arrays.asList(studentId, destStudentId));
        Map<Long,Student> studentMap = BeanUtils.toMap(students,"studentId");
        Student student = studentMap.get(studentId);
        Student destStudent = studentMap.get(destStudentId);
        jsonObject.put("tag" ,"student");
        jsonObject.put("studentNo",student.getStudentNo());
        jsonObject.put("name",student.getName());
        jsonObject.put("phoneNo",student.getPhoneNo());
        jsonObject.put("gradeName",student.getGradeName());
        jsonObject.put("school",student.getSchool());

        jsonObject.put("destStudentNo",destStudent.getStudentNo());
        jsonObject.put("destName",destStudent.getName());
        jsonObject.put("destPhoneNo",destStudent.getPhoneNo());
        jsonObject.put("destGradeName",destStudent.getGradeName());
        jsonObject.put("destSchool",destStudent.getSchool());

        return jsonObject ;
    }
}